home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Kit PC World De Ampliacion De Windows 95
/
Kit PC World de ampliacion de Windows 95.iso
/
internet
/
sweeper
/
samples
/
docobj
/
framer.cpp
next >
Wrap
C/C++ Source or Header
|
1995-11-22
|
32KB
|
1,338 lines
/*
* FRAMER.CPP
* Document Objects Framer
*
* Sample to demonstrate in-place activation of a DocObject--also
* activates normal embeddings in separate windows.
*
* Copyright (c)1995 Microsoft Corporation, All Rights Reserved
* Kraig Brockschmidt, kraigb@microsoft.com
*/
#define INITGUID
#include "framer.h"
/*
* WinMain
*
* Purpose:
* Main entry point of application. Should register the app class
* if a previous instance has not done so and do any other one-time
* initializations.
*/
int PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrev
, LPSTR pszCmdLine, int nCmdShow)
{
PCFrame pFR;
WPARAM wRet;
//Attempt to allocate and initialize the application
pFR=new CFrame(hInst, hPrev, pszCmdLine, nCmdShow);
if (NULL==pFR)
return 0;
//If we can initialize pFR, start chugging messages
if (pFR->Init(CMENUS, CW_USEDEFAULT, CW_USEDEFAULT
, CW_USEDEFAULT, CW_USEDEFAULT))
wRet=pFR->MessageLoop();
delete pFR;
return wRet;
}
/*
* CFrame::CFrame
* CFrame::~CFrame
*
* Constructor Parameters:
* hInst HINSTANCE from WinMain
* hInstPrev HINSTANCE from WinMain
* pszCmdLine LPSTR from WinMain
* nCmdShow int from WinMain
*/
CFrame::CFrame(HINSTANCE hInst, HINSTANCE hInstPrev
, LPSTR pszCmdLine, int nCmdShow)
{
m_hInst=hInst;
m_hWnd=NULL;
m_hInstPrev=hInstPrev;
m_nCmdShow=nCmdShow;
m_phMenu=NULL;
m_hAccel=NULL;
m_hWndClient=NULL;
m_fInitialized=FALSE;
m_pIStorage=NULL;
m_dwIDCounter=0;
m_hMenuOrg=NULL;
m_hMenuTop=NULL;
m_hMenuHelp=NULL;
m_fInObjectHelp=FALSE;
m_fUsingOurHelp=FALSE;
m_fHaveObject=FALSE;
m_hWndObj=NULL;
m_pSite=NULL;
m_fOurMenuShowing=TRUE;
SetRect(&m_bwIP, 0, 0, 0, 0);
m_fInContextHelp=FALSE;
m_pIOleIPActiveObject=NULL;
return;
}
CFrame::~CFrame(void)
{
if (NULL!=m_hWndClient)
DestroyWindow(m_hWndClient);
//Frees the temp file.
ReleaseInterface(m_pIStorage);
//m_pSite cleaned up in Close
//Accelerators freed automatically.
//Destroy the special help menu
if (NULL!=m_hMenuHelp)
DestroyMenu(m_hMenuHelp);
//Free the menu handle array
if (NULL!=m_phMenu)
delete []((UINT *)m_phMenu);
if (m_fInitialized)
OleUninitialize();
return;
}
/*
* CFrame::Init
*
* Purpose:
* Initializer for a CFrame object containing anything prone to
* failure.
*
* Parameters:
* cMenus UINT number of menus on the frame
* x, y, cx, cy int location and size of frame window
*
* Return Value:
* BOOL TRUE if initialization succeeded, FALSE
* otherwise. If FALSE is returned, the caller must
* guarantee that the destructor is called promptly
* to insure cleanup.
*/
BOOL CFrame::Init(UINT cMenus, int x, int y, int cx, int cy)
{
HMENU hMenu;
UINT uTemp;
RECT rc;
//1. Initialize OLE
if (SUCCEEDED(OleInitialize(NULL)))
m_fInitialized=TRUE;
else
return FALSE;
//2. Register window classes
if (NULL==m_hInstPrev)
{
if (!RegisterAllClasses())
return FALSE;
}
//3. Create the main window and client-area window
m_hWnd=CreateWindow(SZCLASSFRAME, TEXT("DocObject Framer")
, WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
, x, y, cx, cy, NULL, NULL, m_hInst, this);
if (NULL==m_hWnd)
return FALSE;
GetClientRect(m_hWnd, &rc);
m_hWndClient=CreateWindow(SZCLASSCLIENT, SZCLASSCLIENT
, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_CLIPSIBLINGS
, rc.left, rc.top, rc.right-rc.left
, rc.bottom-rc.top, m_hWnd, NULL, m_hInst, this);
if (NULL==m_hWndClient)
return FALSE;
//4. Allocate menu array for use with in-place menu merging.
m_phMenu=new HMENU[cMenus];
hMenu=GetMenu(m_hWnd);
m_hMenuOrg=hMenu;
for (uTemp=0; uTemp < cMenus; uTemp++)
m_phMenu[uTemp]=GetSubMenu(hMenu, uTemp);
//Also load the special help menu
m_hMenuHelp=LoadMenu(m_hInst
, MAKEINTRESOURCE(IDR_MENUHELP));
//5. Load accelerators
m_hAccel=LoadAccelerators(m_hInst
, MAKEINTRESOURCE(IDR_ACCELERATORS));
if (NULL==m_hAccel)
return FALSE;
//6. Make us all visible.
ShowWindow(m_hWnd, m_nCmdShow);
UpdateWindow(m_hWnd);
/*
* 7. Create a temp file for all embedded files. Note that in this
* sample we don't save any changes to DocObjects because we
* don't manage any storage directly.
*/
if (FAILED(StgCreateDocfile(NULL, STGM_TRANSACTED | STGM_READWRITE
| STGM_SHARE_EXCLUSIVE | STGM_CREATE| STGM_DELETEONRELEASE
, 0, &m_pIStorage)))
return FALSE;
return TRUE;
}
/*
* CFrame::RegisterAllClasses
*
* Purpose:
* Registers all classes used in this application.
*
* Return Value:
* BOOL TRUE if registration succeeded, FALSE otherwise.
*/
BOOL CFrame::RegisterAllClasses(void)
{
WNDCLASS wc;
//Field that are the same for all windows.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = m_hInst;
wc.cbClsExtra = 0;
//Register the Frame window
wc.lpfnWndProc = FrameWndProc;
wc.cbWndExtra = CBFRAMEWNDEXTRA;
wc.hIcon = LoadIcon(m_hInst, TEXT("Icon"));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = SZCLASSFRAME;
if (!RegisterClass(&wc))
return FALSE;
//Register the do-nothing Client window
wc.lpfnWndProc = ClientWndProc;
wc.cbWndExtra = CBCLIENTWNDEXTRA;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = SZCLASSCLIENT;
if (!RegisterClass(&wc))
return FALSE;
return TRUE;
}
/*
* CFrame::OnCommand
*
* Purpose:
* WM_COMMAND handler for the frame window so derivations can
* process their messages and then pass the standard commands (like
* file open and save) on to the base class.
*
* Parameters:
* hWnd HWND of the frame window.
* wParam WPARAM of the message.
* lParam LPARAM of the message.
*
* Return Value:
* LRESULT Return value for the message.
*/
LRESULT CFrame::OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
TCHAR szFile[MAX_PATH];
BOOL fOK;
PCHourglass pHour;
WORD wID=LOWORD(wParam);
switch (wID)
{
case IDM_FILEOPEN:
/*
* This will be disabled if we already have an object.
* User must File/Close first to get back here.
*
* Otherwise open the File/Open dialog
*/
szFile[0]=0;
if (!OpenDialog(szFile, MAX_PATH))
return 0L;
pHour=new CHourglass;
fOK=CreateObject(szFile);
delete pHour;
return 0;
case IDM_FILECLOSE:
Close();
break;
case IDM_FILEEXIT:
PostMessage(hWnd, WM_CLOSE, 0, 0L);
break;
case IDM_HELPABOUT:
DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUT)
, m_hWnd, (DLGPROC)AboutProc);
break;
case IDM_ENTERCONTEXTHELP:
case IDM_ESCAPECONTEXTHELP:
//Notify the object on entry and exit.
ContextSensitiveHelp(IDM_ENTERCONTEXTHELP==wID);
break;
default:
return DefWindowProc(hWnd, WM_COMMAND, wParam, lParam);
}
return 0L;
}
/*
* CFrame::OpenDialog
*
* Purpose:
* Invokes the COMMDLG.DLL GetOpenFileName dialog and retrieves
* a filename for saving or opening.
*
* Parameters:
* pszFile LPTSTR buffer to receive the entered filename.
* cchFile UINT length of pszFile
*
* Return Value:
* BOOL TRUE if the function retrieved a filename,
* FALSE if the user pressed CANCEL.
*/
BOOL CFrame::OpenDialog(LPTSTR pszFile, UINT cchFile)
{
OPENFILENAME ofn;
static TCHAR szFilter[80]=TEXT("All Files (*.*)\0*.*\0\0");
BOOL fRet;
#ifdef DEBUG
DWORD dwErr;
#endif
if (NULL==pszFile)
return FALSE;
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize =sizeof(OPENFILENAME);
ofn.hwndOwner =m_hWnd;
ofn.lpstrFilter =szFilter;
ofn.nFilterIndex =1L;
ofn.lpstrTitle =NULL;
ofn.lpstrFile =pszFile;
ofn.nMaxFile =cchFile;
ofn.lpstrDefExt =TEXT("*");
ofn.Flags =OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
fRet=GetOpenFileName(&ofn);
#ifdef DEBUG
dwErr=CommDlgExtendedError();
#endif
return fRet;
}
/*
* CFrame::CreateObject
*
* Purpose:
* Creates a site and has it create an object based on a filename.
*
* Parameters:
* pszFile LPTSTR pointing to the filename from which to
* create the object.
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CFrame::CreateObject(LPTSTR pszFile)
{
m_pSite=new CSite(++m_dwIDCounter, m_hWndClient, this);
if (NULL==m_pSite)
return FALSE;
m_pSite->AddRef(); //So we can free with Release
/*
* Now tell the site to create an object in it using the filename
* and the storage we opened. The site will create a sub-storage
* for the doc object's use.
*/
if (!m_pSite->Create(pszFile, m_pIStorage))
return FALSE;
m_fHaveObject=TRUE;
//We created the thing, now activate it with "Show"
m_pSite->Activate(OLEIVERB_SHOW);
//Force repaint to show "have object" message
InvalidateRect(m_hWndClient, NULL, TRUE);
UpdateWindow(m_hWndClient);
return TRUE;
}
/*
* CFrame::Close
*
* Purpose:
* Handles File/Close by freeing the object and resetting the
* application state.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CFrame::Close(void)
{
RECT rc;
if (NULL!=m_pSite)
{
m_pSite->Close(FALSE); //Frees the object
m_pSite->Destroy(m_pIStorage); //Cleans up the storage
m_pSite->Release(); //Frees the site
}
m_fHaveObject=FALSE;
SetRect(&m_bwIP, 0, 0, 0, 0);
GetClientRect(m_hWnd, &rc);
ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
, rc.bottom-rc.top);
//Force repaint to remove "have object" message
InvalidateRect(m_hWndClient, NULL, TRUE);
UpdateWindow(m_hWndClient);
return;
}
/*
* CFrame::ResizeClientWindow
*
* Purpose:
* Resizes the client-area window according to current toolbar sizes
* and the frame window size.
*
* Parameters:
* x,y,cx,cy UINT origin and dimensions of the window
*
* Return Value:
* None
*/
void CFrame::ResizeClientWindow(UINT x, UINT y, UINT cx, UINT cy)
{
SetWindowPos(m_hWndClient, NULL, x, y, cx, cy
, SWP_NOZORDER | SWP_NOACTIVATE);
//Tell the site to tell the object.
if (NULL!=m_pSite)
m_pSite->UpdateObjectRects();
return;
}
/*
* CFrame::MessageLoop
*
* Purpose:
* Spins in a standard message loop (with accelerators) until
* WM_QUIT is found after which it returns.
*
* Return Value:
* WPARAM Contents of msg.wParam from WM_QUIT.
*/
WPARAM CFrame::MessageLoop(void)
{
MSG msg;
while (GetMessage(&msg, NULL, 0,0 ))
{
//Always give the object first crack at translation.
if (NULL!=m_pIOleIPActiveObject)
{
HRESULT hr;
hr=m_pIOleIPActiveObject->TranslateAccelerator(&msg);
//If the object translated the accelerator, we're done
if (NOERROR==hr)
continue;
}
if (!::TranslateAccelerator(m_hWnd, m_hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
/*
* FrameWndProc
*
* Purpose:
* Frame window class procedure that allows a derivation of these
* classes to hook and process any messages desired. Otherwise this
* handles standard commands as well as the status line and menus.
*/
LRESULT APIENTRY FrameWndProc(HWND hWnd, UINT iMsg
, WPARAM wParam, LPARAM lParam)
{
PCFrame pFR;
RECT rc;
HMENU hMenu;
pFR=(PCFrame)GetWindowLong(hWnd, FRAMEWL_STRUCTURE);
switch (iMsg)
{
case WM_NCCREATE:
pFR=(PCFrame)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLong(hWnd, FRAMEWL_STRUCTURE, (LONG)pFR);
return DefWindowProc(hWnd, iMsg, wParam, lParam);
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CLOSE:
pFR->Close();
DestroyWindow(hWnd);
break;
case WM_ERASEBKGND:
//Client area window always manages painting
return FALSE;
case WM_SIZE:
//Tell the in-place object about the new frame size
GetClientRect(hWnd, &rc);
if (NULL!=pFR->m_pIOleIPActiveObject)
pFR->m_pIOleIPActiveObject->ResizeBorder(&rc, pFR, TRUE);
/*
* Resize the client, which is done in all cases since this window
* is the parent of the DocObject, plus we need to tell the
* DocObject of the new size through IOleDocumentView::SetRect.
*/
rc.left +=pFR->m_bwIP.left;
rc.right -=pFR->m_bwIP.right;
rc.top +=pFR->m_bwIP.top;
rc.bottom-=pFR->m_bwIP.bottom;
pFR->ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
, rc.bottom-rc.top);
break;
case WM_SETFOCUS:
if (NULL!=pFR->m_pIOleIPActiveObject)
{
HWND hWndObj;
pFR->m_pIOleIPActiveObject->GetWindow(&hWndObj);
SetFocus(hWndObj);
}
return TRUE;
case WM_INITMENU:
pFR->m_fInObjectHelp=FALSE;
break;
case WM_MENUSELECT:
{
UINT fuFlags=(UINT)HIWORD(wParam);
UINT uItem=(UINT)LOWORD(wParam);
if (MF_POPUP & fuFlags)
{
/*
* If we're inside our m_hMenuHelp, and uItem is
* not zero (first item on the menu, which is ours),
* then we must be in an object-supplied menu.
*
* Therefore we set our flag and forward the message
* as well as others that occur later. Otherwise we
* clear the flag so we get messages again.
*/
if (NULL!=pFR->m_hMenuHelp
&& (HMENU)lParam==pFR->m_hMenuHelp)
{
pFR->m_fInObjectHelp=(0!=uItem);
if (pFR->m_fInObjectHelp)
SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
}
}
else
{
//Forward the message on
if (pFR->m_fInObjectHelp)
{
SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
break;
}
}
}
break;
case WM_INITMENUPOPUP:
/*
* If we're in the object's Help menu, forward to
* the object received in IOleInPlaceFrame::SetActiveObject
*/
if (pFR->m_fInObjectHelp && NULL!=pFR->m_hWndObj)
SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
//Skip the system menu
if (TRUE==(BOOL)HIWORD(lParam))
break;
/*
* If we have an object, enable Close, otherwise
* enable Open.
*/
hMenu=(HMENU)wParam;
if (hMenu==pFR->m_phMenu[0])
{
UINT uTempE=MF_BYCOMMAND | MF_ENABLED;
UINT uTempD=MF_BYCOMMAND | MF_DISABLED | MF_GRAYED;
EnableMenuItem(hMenu, IDM_FILEOPEN
, pFR->m_fHaveObject ? uTempD : uTempE);
EnableMenuItem(hMenu, IDM_FILECLOSE
, pFR->m_fHaveObject ? uTempE : uTempD);
}
break;
case WM_COMMAND:
if (pFR->m_fInObjectHelp)
{
SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
break;
}
else
return pFR->OnCommand(hWnd, wParam, lParam);
default:
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
return 0L;
}
/*
* ClientWndProc
*
* Purpose:
* Client window class procedure that's only used to paint a
* message when we have a non-DocObject open. Otherwise this
* is completely hidden.
*/
LRESULT APIENTRY ClientWndProc(HWND hWnd, UINT iMsg
, WPARAM wParam, LPARAM lParam)
{
PCFrame pFR;
PAINTSTRUCT ps;
pFR=(PCFrame)GetWindowLong(hWnd, CLIENTWL_STRUCTURE);
switch (iMsg)
{
case WM_NCCREATE:
pFR=(PCFrame)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLong(hWnd, CLIENTWL_STRUCTURE, (LONG)pFR);
return DefWindowProc(hWnd, iMsg, wParam, lParam);
case WM_PAINT:
BeginPaint(hWnd, &ps);
if (pFR->m_fHaveObject)
{
static TCHAR szMsg[]={TEXT("A non-DocObject is open or loaded. Use File/Close to destroy it.")};
SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
TextOut(ps.hdc, 0, 0, szMsg, lstrlen(szMsg));
}
EndPaint(hWnd, &ps);
break;
default:
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
return 0L;
}
/*
* AboutProc
*
* Purpose:
* Dialog procedure for the omnipresent About box.
*
* Parameters:
* The standard.
*
* Return Value:
* The value to be returned through the DialogBox call that
* created the dialog.
*
*/
BOOL APIENTRY AboutProc(HWND hDlg, UINT iMsg
, WPARAM wParam, LPARAM lParam)
{
switch (iMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, TRUE);
}
break;
}
return FALSE;
}
/*
* IOleInPlaceFrame implementation
*/
/*
* CFrame::QueryInterface
* CFrame::AddRef
* CFrame::Release
*/
STDMETHODIMP CFrame::QueryInterface(REFIID riid, void **ppv)
{
//We only know IOleInPlaceFrame and it's base interfaces
*ppv=NULL;
if (IID_IUnknown==riid || IID_IOleInPlaceUIWindow==riid
|| IID_IOleWindow==riid || IID_IOleInPlaceFrame==riid)
*ppv=this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CFrame::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CFrame::Release(void)
{
//Nothing special happening here--frame's life if user-controlled.
return --m_cRef;
}
/*
* CFrame::GetWindow
*
* Purpose:
* Retrieves the handle of the window associated with the object
* on which this interface is implemented.
*
* Parameters:
* phWnd HWND * in which to store the window handle.
*
* Return Value:
* HRESULT NOERROR if successful, E_FAIL if there is no
* window.
*/
STDMETHODIMP CFrame::GetWindow(HWND *phWnd)
{
*phWnd=m_hWnd;
return NOERROR;
}
/*
* CFrame::ContextSensitiveHelp
*
* Purpose:
* Instructs the object on which this interface is implemented to
* enter or leave a context-sensitive help mode.
*
* Parameters:
* fEnterMode BOOL TRUE to enter the mode, FALSE otherwise.
*
* Return Value:
* HRESULT NOERROR
*/
STDMETHODIMP CFrame::ContextSensitiveHelp(BOOL fEnterMode)
{
/*
* Don't bother if there is no active object since we don't do
* context help on our own.
*/
if (NULL==m_pIOleIPActiveObject)
return NOERROR;
//If the state changes, notify the active object.
if (m_fInContextHelp!=fEnterMode)
{
m_fInContextHelp=fEnterMode;
m_pIOleIPActiveObject->ContextSensitiveHelp(fEnterMode);
}
return NOERROR;
}
/*
* CFrame::GetBorder
*
* Purpose:
* Returns the rectangle in which the container is willing to
* negotiate about an object's adornments.
*
* Parameters:
* prcBorder LPRECT in which to store the rectangle.
*
* Return Value:
* HRESULT NOERROR if all is well, INPLACE_E_NOTOOLSPACE
* if there is no negotiable space.
*/
STDMETHODIMP CFrame::GetBorder(LPRECT prcBorder)
{
if (NULL==prcBorder)
return E_INVALIDARG;
//We return all the client area space
GetClientRect(m_hWnd, prcBorder);
return NOERROR;
}
/*
* CFrame::RequestBorderSpace
*
* Purpose:
* Asks the container if it can surrender the amount of space
* in pBW that the object would like for it's adornments. The
* container does nothing but validate the spaces on this call.
*
* Parameters:
* pBW LPCBORDERWIDTHS containing the requested space.
* The values are the amount of space requested
* from each side of the relevant window.
*
* Return Value:
* HRESULT NOERROR if we can give up space,
* INPLACE_E_NOTOOLSPACE otherwise.
*/
STDMETHODIMP CFrame::RequestBorderSpace(LPCBORDERWIDTHS pBW)
{
//Framer has no border space restrictions
return NOERROR;
}
/*
* CFrame::SetBorderSpace
*
* Purpose:
* Called when the object now officially requests that the
* container surrender border space it previously allowed
* in RequestBorderSpace. The container should resize windows
* appropriately to surrender this space.
*
* Parameters:
* pBW LPCBORDERWIDTHS containing the amount of space
* from each side of the relevant window that the
* object is now reserving.
*
* Return Value:
* HRESULT NOERROR
*/
STDMETHODIMP CFrame::SetBorderSpace(LPCBORDERWIDTHS pBW)
{
RECT rc;
/*
* Since we have no tools, we can accept anything the object sends
* and must therefore adjust the client-area window accordingly.
*/
/*
* If pBW is NULL, the object is not interested in tools, so we
* don't have to do anything. In either case we need to save
* the toolspace allocations in order to resize the client window
* correctly.
*/
if (NULL==pBW)
{
if (!m_fOurMenuShowing)
SetMenu(NULL, NULL, NULL);
SetRect(&m_bwIP, 0, 0, 0, 0);
return NOERROR;
}
else
{
GetClientRect(m_hWnd, &rc);
rc.left +=pBW->left;
rc.right -=pBW->right;
rc.top +=pBW->top;
rc.bottom-=pBW->bottom;
m_bwIP=*pBW;
}
ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
, rc.bottom-rc.top);
return NOERROR;
}
/*
* CFrame::SetActiveObject
*
* Purpose:
* Provides the container with the object's IOleInPlaceActiveObject
* pointer
*
* Parameters:
* pIIPActiveObj LPOLEINPLACEACTIVEOBJECT of interest.
* pszObj LPCOLESTR naming the object. Not used.
*
* Return Value:
* HRESULT NOERROR
*/
STDMETHODIMP CFrame::SetActiveObject
(LPOLEINPLACEACTIVEOBJECT pIIPActiveObj, LPCOLESTR pszObj)
{
if (NULL!=m_pIOleIPActiveObject)
m_pIOleIPActiveObject->Release();
//NULLs m_pIOleIPActiveObject if pIIPActiveObj is NULL
m_pIOleIPActiveObject=pIIPActiveObj;
if (NULL!=m_pIOleIPActiveObject)
m_pIOleIPActiveObject->AddRef();
m_pIOleIPActiveObject->GetWindow(&m_hWndObj);
return NOERROR;
}
/*
* CFrame::InsertMenus
*
* Purpose:
* Instructs the container to place its in-place menu items where
* necessary in the given menu and to fill in elements 0, 2, and 4
* of the OLEMENUGROUPWIDTHS array to indicate how many top-level
* items are in each group.
*
* Parameters:
* hMenu HMENU in which to add popups.
* pMGW LPOLEMENUGROUPWIDTHS in which to store the
* width of each container menu group.
*
* Return Value:
* HRESULT NOERROR
*/
STDMETHODIMP CFrame::InsertMenus(HMENU hMenu
, LPOLEMENUGROUPWIDTHS pMGW)
{
//Copy our File menu into the shared menu.
InsertMenu(hMenu, 0, MF_BYPOSITION | MF_POPUP, (UINT)m_phMenu[0]
, TEXT("&File"));
pMGW->width[0]=1;
pMGW->width[2]=0;
pMGW->width[4]=0;
/*
* Add the special help menu which is the first item in
* the m_hMenuHelp popup that's sitting around.
*/
InsertMenu(hMenu, 1, MF_BYPOSITION | MF_POPUP
, (UINT)m_hMenuHelp, TEXT("&Help"));
//Tell the object we added our Help menu
pMGW->width[5]=1;
return NOERROR;
}
/*
* CFrame::SetMenu
*
* Purpose:
* Instructs the container to replace whatever menu it's currently
* using with the given menu and to call OleSetMenuDescritor so OLE
* knows to whom to dispatch messages.
*
* Parameters:
* hMenu HMENU to show.
* hOLEMenu HOLEMENU to the menu descriptor.
* hWndObj HWND of the active object to which messages are
* dispatched.
*
* Return Value:
* HRESULT NOERROR
*/
STDMETHODIMP CFrame::SetMenu(HMENU hMenu, HOLEMENU hOLEMenu
, HWND hWndObj)
{
HRESULT hr;
/*
* Our responsibilities here are to put the menu on the frame
* window and call OleSetMenuDescriptor.
*/
if (NULL==hMenu)
{
//Prevent redundant calls, or debug warnings on startup.
if (NULL==m_hMenuTop)
return NOERROR;
hMenu=m_hMenuTop;
m_hMenuTop=NULL;
m_fOurMenuShowing=TRUE;
}
else
{
m_hMenuTop=m_hMenuOrg;
m_fOurMenuShowing=FALSE;
/*
* Check if our Help menu has anything added to it. If so, then
* remember to forward menu messages. If not, remove the Help
* menu altogether (destroying it after removing our normal Help
* popup, as we also do in RemoveMenus.
*/
if (CHELPITEMS!=GetMenuItemCount(m_hMenuHelp))
m_fUsingOurHelp=TRUE;
else
{
UINT i, cItems;
cItems=GetMenuItemCount(hMenu);
//Find m_hMenuHelp in the menu and remove it.
for (i=0; i < cItems; i++)
{
if (GetSubMenu(hMenu, i)==m_hMenuHelp)
{
RemoveMenu(hMenu, i, MF_BYPOSITION);
break;
}
}
}
}
if (NULL!=hMenu)
::SetMenu(m_hWnd, hMenu);
DrawMenuBar(m_hWnd);
hr=OleSetMenuDescriptor(hOLEMenu, m_hWnd, hWndObj, NULL, NULL);
return hr;
}
/*
* CFrame::RemoveMenus
*
* Purpose:
* Asks the container to remove any menus it put into hMenu in
* InsertMenus.
*
* Parameters:
* hMenu HMENU from which to remove the container's
* items.
*
* Return Value:
* HRESULT NOERROR
*/
STDMETHODIMP CFrame::RemoveMenus(HMENU hMenu)
{
int cItems, i, j;
HMENU hMenuT;
/*
* To be defensive, loop through this menu removing anything
* we recognize (that is, anything in m_phMenu) just in case
* the server didn't clean it up right. At least we can
* give ourselves the prophylactic benefit.
*/
if (NULL==hMenu)
return NOERROR;
cItems=GetMenuItemCount(hMenu);
/*
* Walk backwards down the menu. For each popup, see if it
* matches any other popup we know about, and if so, remove
* it from the shared menu.
*/
for (i=cItems; i >=0; i--)
{
hMenuT=GetSubMenu(hMenu, i);
for (j=0; j <= CMENUS; j++)
{
//Remove any owned popup, or our special help menu
if (hMenuT==m_phMenu[j]
|| (hMenuT==m_hMenuHelp && m_hMenuHelp!=NULL))
RemoveMenu(hMenu, i, MF_BYPOSITION);
}
}
m_fUsingOurHelp=FALSE;
//The menu should now be empty.
return NOERROR;
}
/*
* CFrame::SetStatusText
*
* Purpose:
* Asks the container to place some text in a status line, if one
* exists. If the container does not have a status line it
* should return E_FAIL here in which case the object could
* display its own.
*
* Parameters:
* pszText LPCOLESTR to display.
*
* Return Value:
* HRESULT NOERROR if successful, S_TRUNCATED if not all
* of the text could be displayed, or E_FAIL if
* the container has no status line.
*/
STDMETHODIMP CFrame::SetStatusText(LPCOLESTR pszText)
{
//We have no status line...
return E_NOTIMPL;
}
/*
* CFrame::EnableModeless
*
* Purpose:
* Instructs the container to show or hide any modeless popup
* windows that it may be using.
*
* Parameters:
* fEnable BOOL indicating to enable/show the windows
* (TRUE) or to hide them (FALSE).
*
* Return Value:
* HRESULT NOERROR
*/
STDMETHODIMP CFrame::EnableModeless(BOOL fEnable)
{
return NOERROR;
}
/*
* CFrame::TranslateAccelerator
*
* Purpose:
* When dealing with an in-place object from an EXE server, this
* is called to give the container a chance to process accelerators
* after the server has looked at the message.
*
* Parameters:
* pMSG LPMSG for the container to examine.
* wID WORD the identifier in the container's
* accelerator table (from IOleInPlaceSite
* ::GetWindowContext) for this message (OLE does
* some translation before calling).
*
* Return Value:
* HRESULT NOERROR if the keystroke was used,
* S_FALSE otherwise.
*/
STDMETHODIMP CFrame::TranslateAccelerator(LPMSG pMSG, WORD wID)
{
/*
* wID already has anything translated from m_hAccel for us,
* so we can just check for the commands we want and process
* them instead of calling TranslateAccelerator which would be
* redundant and which also has a possibility of dispatching to
* the wrong window.
*/
if (IDM_ENTERCONTEXTHELP==wID || IDM_ESCAPECONTEXTHELP==wID)
{
//wID properly expands to 32-bits
OnCommand(m_hWnd, (WPARAM)wID, 0L);
return NOERROR;
}
return S_FALSE;
}